package cn.openread.es;

import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 用途：一切为了业务
 * *
 * {
 * "id":10001,
 * "name":"张相逢",
 * "idCard":"410482199406309336",
 * "description":"Simon 是个帅哥,有文化的人。",
 * "point":98.6,
 * "createTime":"2020-02-02"
 * }
 * <p>
 * matchQuery：词条匹配，先分词然后在调用termQuery进行匹配
 * <p>
 * TermQuery：词条匹配，不分词
 * <p>
 * wildcardQuery：通配符匹配
 * <p>
 * fuzzyQuery：模糊匹配
 * <p>
 * rangeQuery：范围匹配
 * <p>
 * booleanQuery：布尔查询
 * <p>
 * Created by simon on 2020/3/7.
 */
@RestController
@RequestMapping("/item")
public class EsItemController {
    @Autowired
    private ItemRepository itemRepository;

    @Autowired
    private ReactiveElasticsearchTemplate reactiveElasticsearchTemplate;

    @GetMapping("/{id}")
    public Object get(@PathVariable("id") Long id) {
        return this.itemRepository.findById(id);
    }


    @RequestMapping(value = "", method = {RequestMethod.POST, RequestMethod.PUT})
    public Mono<Item> save(@RequestBody Item item) {
        Mono<Item> mono = this.itemRepository.save(item);
        return mono;
    }

    @DeleteMapping("/{id}")
    public void deleteById(@PathVariable("id") Long id) {
        this.itemRepository.deleteById(id);
    }

    @DeleteMapping("/deleteAll")
    public void deleteAll() {
        this.itemRepository.deleteAll();
    }

    @GetMapping("/findByName")
    public Object findByName(@RequestParam(name = "name") String name) {
        Flux<Item> flux = this.itemRepository.findAllByNameContains(name);
        return flux;
    }

    @GetMapping("/findAll")
    public Object findAll() {
        Flux<Item> flux = this.itemRepository.findAll();
        return flux;
    }

    @GetMapping("/search")
    public Object search(
            @RequestParam(name = "id", required = false) Long id,
            @RequestParam(name = "name", required = false) String name,
            @RequestParam(name = "description", required = false) String description,
            @RequestParam(name = "idCard", required = false) String idCard,
            @RequestParam(name = "gtPoint", required = false) Double gtPoint,
            @RequestParam(name = "ltPoint", required = false) Double ltPoint,

            @RequestParam(name = "limit", required = false) Integer limit,
            @RequestParam(name = "page", required = false) Integer page) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        PageRequest pageRequest = PageRequest.of(page - 1, limit, Sort.by(Sort.Order.asc("id")));

        if (id != null) {
            queryBuilder.withQuery(QueryBuilders.termQuery("id", id));
        }
        if (!StringUtils.isEmpty(name)) {
            queryBuilder.withQuery(QueryBuilders.fuzzyQuery("name", name));
        }

        if (!StringUtils.isEmpty(description)) {
            HighlightBuilder.Field field = new HighlightBuilder.Field("description").preTags("#").postTags("#");
            queryBuilder.withQuery(QueryBuilders.matchQuery("description", description))
                    .withHighlightFields(field);
        }

        if (!StringUtils.isEmpty(idCard)) {
            queryBuilder.withQuery(QueryBuilders.termQuery("idCard", idCard));
        }

        if (gtPoint != null) {
            queryBuilder.withQuery(QueryBuilders.rangeQuery("point").gte(gtPoint));
        }
        if (ltPoint != null) {
            queryBuilder.withQuery(QueryBuilders.rangeQuery("point").lte(ltPoint));
        }

        Flux<Item> flux = this.reactiveElasticsearchTemplate.find(queryBuilder.withPageable(pageRequest).build(), Item.class);
        return flux;
    }
}
